/**
 * @file SoftI2C.h
 * @author hpy (yuan_hp@qq.com)
 * @brief 基于FPGA上serv软核MCU的I2C 控制器，需要配合FPGA逻辑处理SDA信号线
 * @version 0.1
 * @date 2024-07-11
 * 
 * @copyright Copyright (c) 2024
 * 
 */
#ifndef __SOFTI2C_H__
#define __SOFTI2C_H__

#include "platform.h"

#define SOFT_I2C_MORE_BYTE_ENABLE  0 //  1: 使能多字节读写操作
#define SOFT_I2C_USE_FUNCTION      0 //   1: 使用function读写IO


// --------------------------------- 定义外设控制的函数 --------------------------------------
#define  SOFT_I2C_EEPROM_M24M01_RMN6TP_ENABLE  0   // 使能EEPROM M24M01_RMN6TP 1Mbit
#define  SOFT_I2C_LM75_ENABLE                  0   // 使能 LM75 温度传感器
#define  SOFT_I2C_AHT10_ENABLE                 1   // 使能 AHT10 温湿度传感器
// ------------------------------------------------------------------------------------------


#if(SOFT_I2C_USE_FUNCTION == 1)
#define SDA_H() Serv_PinSet(i2c->port,i2c->sda_pin)
#define SDA_L() Serv_PinReset(i2c->port,i2c->sda_pin)
#define SDA()   Serv_PinGet(i2c->port,i2c->sda_pin)
#define SCL_H() Serv_PinSet(i2c->port,i2c->scl_pin)
#define SCL_L() Serv_PinReset(i2c->port,i2c->scl_pin)
#else 
#define SDA_H()    (*i2c->port = *(i2c->port+1) | (0x1u<< i2c->sda_pin))
#define SDA_L()    (*i2c->port = *(i2c->port+1) & (~(0x1u<< i2c->sda_pin)) )
#define SDA()      ((*(i2c->port+1)>>i2c->sda_pin)&0x1u)     //((*i2c->port>>i2c->sda_pin)&0x1u)
#define SCL_H()    (*i2c->port =*(i2c->port+1) |( 0x1u<< i2c->scl_pin) )
#define SCL_L()    (*i2c->port = *(i2c->port+1) & (~(0x1u<< i2c->scl_pin)) )
#endif

#define IIC_Delay()    //SoftI2C_DelayTik(i2c->delay_ticks)


#define SOFT_IIC_DEBUG 0

#if (SOFT_IIC_DEBUG==1) 
#include "SoftUart.h"
#define IIC_DEBUG(x) do{ \
    TxStr(x);\
    TxStr("\r\n");\
} while(0)
#else 
#define IIC_DEBUG(x) 
#endif 

/**
 * @brief I2C结构体
 * 
 */
typedef struct __si2c_t__ {
    volatile uint32_t  *port     ;
    uint8_t          scl_pin   ;
    uint8_t          sda_pin   ;
    uint8_t delay_ticks ;
} I2C_t ;


/**
 * @brief 软件I2C初始化配置
 * 
 * @param i2c 
 * @param _port 
 * @param scl_pin 
 * @param sda_pin 
 * @param delay_ticks 
 */
void SoftI2C_Init(
    I2C_t *i2c ,
    volatile uint32_t * _port ,     
    uint8_t          scl_pin   ,
    uint8_t          sda_pin ,
    uint8_t delay_ticks 
)  ;

void SoftI2C_DelayTik(const volatile uint8_t x)  ;

/**
 * @brief IIC起始信号
 * 
 * @param i2c 
 */
void SoftI2C_Start(I2C_t *i2c) ; 

/**
 * @brief IIC停止信号
 * 
 * @param i2c 
 */
void SoftI2C_Stop(I2C_t *i2c) ;

/**
 * @brief I2C发送字节函数
 * 
 * @param i2c  i2c控制器对象
 * @param Byte Byte要发送的字节内容
 */
void SoftI2C_SendByte(I2C_t *i2c , uint8_t Byte) ;

/**
 * @brief I2C接收字节函数
 * 
 * @param i2c i2c控制器对象
 * @return uint8_t 接收到的数据
 */
uint8_t SoftI2C_ReceiveByte(I2C_t *i2c ) ; 

/**
 * @brief IIC发送应答信号
 * 
 * @param i2c i2c 控制器对象
 * @param AckBit 应答位，0为应答，1为非应答
 */
void SoftI2C_SendAck(I2C_t *i2c ,volatile uint8_t AckBit) ; 


/**
 * @brief I2C接收应答
 * 
 * @param i2c 
 * @return uint8_t 应答位，0为应答，1为非应答
 */
uint8_t  SoftI2C_ReceiveAck(I2C_t *i2c) ;

uint8_t SoftI2C_Busy(I2C_t *i2c) ;

#if(SOFT_I2C_MORE_BYTE_ENABLE == 1)
uint8_t SoftI2C_Write(I2C_t *i2c , uint8_t deviceaddr , uint8_t *buf , uint8_t bytes);
uint8_t SoftI2C_Read(I2C_t *i2c , uint8_t deviceaddr , uint8_t *buf , uint8_t bytes);
#endif 

#endif 

// ------------------------------ IIC 设备 ------------------------------
#if( SOFT_I2C_EEPROM_M24M01_RMN6TP_ENABLE == 1 )
uint8_t SoftI2C_M24M01_Write(I2C_t *i2c ,uint8_t devaddr , uint16_t addroffset , uint8_t *buf , uint8_t  bytes) ;
uint8_t SoftI2C_M24M01_Read(I2C_t *i2c ,uint8_t devaddr , uint16_t addroffset , uint8_t *buf , uint8_t  bytes) ;
#endif 

#if (  SOFT_I2C_LM75_ENABLE    == 1 ) 
uint8_t SoftI2C_LM75_Read(I2C_t *i2c ,uint8_t devaddr , uint8_t point , uint8_t *buf ) ;
#endif 

#if( SOFT_I2C_AHT10_ENABLE == 1) 
typedef struct __AHT10_t__ {
    I2C_t i2c ;
    int32_t temperature ;
    int32_t humidity ;
} AHT10_t  ; 


uint8_t SoftI2C_AHT10_Init(I2C_t *i2c ) ;
uint8_t SoftI2C_AHT10_Get(I2C_t *i2c , int32_t *humidity , int32_t *temperature ) ;

uint8_t SoftI2C_AHT10_Run(I2C_t *i2c ) ;
#endif 